package com.aplink.generic.xmlpullparser;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.text.TextUtils;
import android.util.Xml;

import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.pojo.AutoSync;
import com.aplink.generic.pojo.CloudNotification;
import com.aplink.generic.pojo.MasterConfig;
import com.aplink.generic.pojo.TableSyncData;
import com.aplink.generic.pojo.WebserviceConfig;
import com.aplink.generic.xmlparser.XmlPaserUtil;

public class MasterConfigXmlPullParser {
	private static final String AUTHORITIES = "Authorities";
	private static final String AUTO_SYNC = "AutoSync";
	private static final String AUTO_SYNC_INTERVAL = "AutoSyncInterval";
	private static final String CHANGE_PASSWORD = "ChangePassword";
	private static final String CONTENT_TITLE = "ContentTitle";
	private static final String DATABASE_NAME = "DatabaseName";
	private static final String DATABASE_UPDATE_INFO = "UpdateInfo";
	private static final String DATABASE_VERSION = "DatabaseVersion";
	private static final String DEMO_DATA = "DemoData";
	private static final String ENABLE = "enable";
	private static final String FORGOT_PASSWORD = "ForgotPassword";
	private static final String ICON = "Icon";
	private static final String INIT_DATA = "InitData";
	private static final String IS_CLEAR_ALL = "isClearAll";
	private static final String IS_DEMO = "isDemo";
	private static final String IS_DOWNLOAD_ONLY = "isDownloadOnly";
	private static final String IS_HAVE_PHOTO = "isHavePhoto";
	private static final String LOGIN_SCREEN = "FirstScreen";
	private static final String MAIN_MENU = "MainMenu";
	private static final String MASTER_CONFIG = "MasterConfig";
	private static final String MESSAGE = "Message";
	private static final String MESSAGE_TAG = "MessageTag";
	private static String mNameSpace = null;
	private static final String NOTIFICATION = "Notification";
	private static final String OFFLINE_MODE = "OfflineMode";
	private static final String SENDER_ID = "SenderID";
	private static final String SYNC_TABLE_LIST = "SyncTableList";
	private static final String TABLE_DOWNLOAD = "TableDownload";
	private static final String TABLE_INIT = "TableInit";
	private static final String TABLE_LIST = "InitTableList";
	private static final String TABLE_STRUCTURE = "TableStructure";
	private static final String TRY_TIME = "TryTimes";
	private static final String UPDATE_LOCATION = "UpdateLocation";
	private static final String WEBSERVICE = "WebService";
	private static final String WEBSERVICE_DOMAIN = "WebserviceDomain";

	private static final String WEBSERVICE_FUNCTION = "WebserviceFunction";

	public static MasterConfig parse(int xmlFile, Context context) {
		InputStream inputStream = XmlPaserUtil.getXMLInputStream(xmlFile,
		        context);
		try {
			XmlPullParser parser = Xml.newPullParser();
			parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
			parser.setInput(inputStream, null);
			parser.nextTag();
			return read(parser);
		} catch (XmlPullParserException | IOException e) {
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return new MasterConfig();
	}

	private static MasterConfig read(XmlPullParser pullParser)
	        throws XmlPullParserException, IOException {
		MasterConfig masterConfig = new MasterConfig();
		pullParser.require(XmlPullParser.START_TAG, mNameSpace, MASTER_CONFIG);
		while (pullParser.next() != XmlPullParser.END_TAG) {
			if (pullParser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}

			if (pullParser.getName().equalsIgnoreCase(DATABASE_NAME)) {
				masterConfig.setDatabaseName(readText(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(DATABASE_VERSION)) {
				masterConfig.setDatabaseVersion(Integer
				        .parseInt(readText(pullParser)));
			} else if (pullParser.getName().equalsIgnoreCase(
			        DATABASE_UPDATE_INFO)) {
				masterConfig.setDatabaseUpdateInfo(readText(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(MAIN_MENU)) {
				masterConfig.setMainMenu(readText(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(TABLE_STRUCTURE)) {
				masterConfig.setTableStructure(readText(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(DEMO_DATA)) {
				setDemoData(pullParser, masterConfig);
			} else if (pullParser.getName().equalsIgnoreCase(OFFLINE_MODE)) {
				masterConfig.setHasOfflineMode(readText(pullParser)
				        .equalsIgnoreCase("ON"));
			} else if (pullParser.getName().equalsIgnoreCase(LOGIN_SCREEN)) {
				masterConfig.setLoginClass(readText(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(TRY_TIME)) {
				masterConfig.setTryTime(Integer.parseInt(readText(pullParser)));
			} else if (pullParser.getName().equalsIgnoreCase(AUTO_SYNC)) {
				readAutoSync(pullParser, masterConfig);
			} else if (pullParser.getName().equalsIgnoreCase(NOTIFICATION)) {
				masterConfig
				        .setCloudNotification(readCloudNotification(pullParser));
			} else if (pullParser.getName().equalsIgnoreCase(WEBSERVICE)) {
				masterConfig.setWebserviceConfig(readWebservice(pullParser));
			} else {
				skip(pullParser);
			}
		}
		return masterConfig;
	}

	private static void readAuthorities(XmlPullParser xmlPullParser,
	        AutoSync autoSync) throws XmlPullParserException, IOException {
		xmlPullParser.require(XmlPullParser.START_TAG, mNameSpace, AUTHORITIES);
		autoSync.setAuthorities(readText(xmlPullParser));
	}

	private static void readAutoSync(XmlPullParser parser,
	        MasterConfig masterConfig) throws XmlPullParserException,
	        IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, AUTO_SYNC);
		AutoSync autoSync = new AutoSync();
		autoSync.setEnable(parser.getAttributeValue(mNameSpace, ENABLE)
		        .equalsIgnoreCase("Y"));
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (parser.getName().equalsIgnoreCase(AUTO_SYNC_INTERVAL)) {
				readAutoSyncInterval(parser, autoSync);
			} else if (parser.getName().equalsIgnoreCase(AUTHORITIES)) {
				readAuthorities(parser, autoSync);
			} else if (parser.getName().equalsIgnoreCase(NOTIFICATION)) {
				readAutoSyncsNotification(parser, autoSync);
			}
		}
		masterConfig.setAutoSync(autoSync);
	}

	private static void readAutoSyncInterval(XmlPullParser xmlPullParser,
	        AutoSync autoSync) throws XmlPullParserException, IOException {
		xmlPullParser.require(XmlPullParser.START_TAG, mNameSpace,
		        AUTO_SYNC_INTERVAL);
		autoSync.setInterval(Integer.parseInt(readText(xmlPullParser)));
	}

	private static void readAutoSyncsNotification(XmlPullParser xmlPullParser,
	        AutoSync autoSync) throws XmlPullParserException, IOException {
		xmlPullParser
		        .require(XmlPullParser.START_TAG, mNameSpace, NOTIFICATION);
		while (xmlPullParser.next() != XmlPullParser.END_TAG) {
			if (xmlPullParser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (xmlPullParser.getName().equalsIgnoreCase(ICON)) {
				autoSync.setIcon(readText(xmlPullParser));
			} else if (xmlPullParser.getName().equalsIgnoreCase(MESSAGE)) {
				autoSync.setMessage(readText(xmlPullParser));
			} else if (xmlPullParser.getName().equalsIgnoreCase(CONTENT_TITLE)) {
				autoSync.setContentTitle(readText(xmlPullParser));
			}
		}
	}

	private static CloudNotification readCloudNotification(
	        XmlPullParser xmlPullParser) throws XmlPullParserException,
	        IOException {
		CloudNotification cloudNotification = new CloudNotification();
		xmlPullParser
		        .require(XmlPullParser.START_TAG, mNameSpace, NOTIFICATION);
		while (xmlPullParser.next() != XmlPullParser.END_TAG) {
			if (xmlPullParser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (xmlPullParser.getName().equalsIgnoreCase(SENDER_ID)) {
				cloudNotification.setSender(readText(xmlPullParser));
			} else if (xmlPullParser.getName().equalsIgnoreCase(ICON)) {
				cloudNotification.setIcon(readText(xmlPullParser));
			} else if (xmlPullParser.getName().equalsIgnoreCase(MESSAGE_TAG)) {
				cloudNotification.setMessageTag(readText(xmlPullParser));
			} else if (xmlPullParser.getName().equalsIgnoreCase(CONTENT_TITLE)) {
				cloudNotification.setContentTitle(readText(xmlPullParser));
			}
		}
		return cloudNotification;
	}

	private static ArrayList<String> readTableInitList(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, TABLE_LIST);
		ArrayList<String> tableInits = new ArrayList<>();
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (parser.getName().equalsIgnoreCase(TABLE_INIT)) {
				tableInits.add(readText(parser));
			}
		}
		return tableInits;
	}

	private static TableSyncData readTableSyncData(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		TableSyncData tableSyncData = new TableSyncData();
		parser.require(XmlPullParser.START_TAG, mNameSpace, TABLE_DOWNLOAD);
		if (!TextUtils.isEmpty(parser.getAttributeValue(mNameSpace,
		        IS_HAVE_PHOTO))) {
			tableSyncData.setHavePhoto(parser.getAttributeValue(mNameSpace,
			        IS_HAVE_PHOTO).equalsIgnoreCase("Y"));
		}

		if (!TextUtils.isEmpty(parser.getAttributeValue(mNameSpace,
		        IS_CLEAR_ALL))) {
			tableSyncData.setClearAll(parser.getAttributeValue(mNameSpace,
			        IS_CLEAR_ALL).equalsIgnoreCase("Y"));
		}

		if (!TextUtils.isEmpty(parser.getAttributeValue(mNameSpace,
		        IS_DOWNLOAD_ONLY))) {
			tableSyncData.setDownloadOnly(parser.getAttributeValue(mNameSpace,
			        IS_DOWNLOAD_ONLY).equalsIgnoreCase("Y"));
		}

		if (!TextUtils.isEmpty(parser.getAttributeValue(mNameSpace,
		        WEBSERVICE_FUNCTION))) {
			tableSyncData.setWebserviceFunction(parser.getAttributeValue(
			        mNameSpace, WEBSERVICE_FUNCTION));
		}
		tableSyncData.setTableName(readText(parser));
		return tableSyncData;
	}

	private static GenericDictionary<String, TableSyncData> readTableSyncDataList(
	        XmlPullParser parser) throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, SYNC_TABLE_LIST);
		GenericDictionary<String, TableSyncData> tableSyncDataList = new GenericDictionary<>();
		TableSyncData tableSyncData = null;
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (parser.getName().equalsIgnoreCase(TABLE_DOWNLOAD)) {
				tableSyncData = readTableSyncData(parser);
				tableSyncDataList.put(tableSyncData.getTableName(),
				        tableSyncData);
			}
		}
		return tableSyncDataList;
	}

	private static String readText(XmlPullParser parser) throws IOException,
	        XmlPullParserException {
		String result = "";
		if (parser.next() == XmlPullParser.TEXT) {
			result = parser.getText();
			parser.nextTag();
		}
		return result;
	}

	private static WebserviceConfig readWebservice(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, WEBSERVICE);
		WebserviceConfig webserviceConfig = new WebserviceConfig();
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}

			if (parser.getName().equalsIgnoreCase(WEBSERVICE_DOMAIN)) {
				webserviceConfig.setWebserviceDomain(readText(parser));
			} else if (parser.getName().equalsIgnoreCase(CHANGE_PASSWORD)) {
				webserviceConfig.setChangePassword(readText(parser));
			} else if (parser.getName().equalsIgnoreCase(FORGOT_PASSWORD)) {
				webserviceConfig.setForgotPassword(readText(parser));
			} else if (parser.getName().equalsIgnoreCase(UPDATE_LOCATION)) {
				webserviceConfig.setUpdateLocation(readText(parser));
			} else if (parser.getName().equalsIgnoreCase(INIT_DATA)) {
				webserviceConfig.setInitData(readText(parser));
			} else if (parser.getName().equalsIgnoreCase(TABLE_LIST)) {
				webserviceConfig.setTableInitLists(readTableInitList(parser));
			} else if (parser.getName().equalsIgnoreCase(SYNC_TABLE_LIST)) {
				webserviceConfig
				        .setTableSyncData(readTableSyncDataList(parser));
			}
		}
		return webserviceConfig;
	}

	private static void setDemoData(XmlPullParser xmlPullParser,
	        MasterConfig masterConfig) throws XmlPullParserException,
	        IOException {
		xmlPullParser.require(XmlPullParser.START_TAG, mNameSpace, DEMO_DATA);
		String value = xmlPullParser.getAttributeValue(mNameSpace, IS_DEMO);
		masterConfig.setDemo(value.equalsIgnoreCase("Y"));
		value = readText(xmlPullParser);
		masterConfig.setDemoData(value);
	}

	private static void skip(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		if (parser.getEventType() != XmlPullParser.START_TAG) {
			throw new IllegalStateException();
		}
		int depth = 1;
		while (depth != 0) {
			switch (parser.next()) {
			case XmlPullParser.END_TAG:
				depth--;
				break;
			case XmlPullParser.START_TAG:
				depth++;
				break;
			}
		}
	}
}
